
#include "SoundEffects.h"
#include <fmod.hpp>

enum SoundType {INVALID_SOUND,LOOPED_STREAM_SOUND,STREAM_SOUND,ROOM_SOUND,LOOPED_ROOM_SOUND};
enum RootSoundDeleteCondition {INVALID_CONDITION,MANUAL_DELETE_CONDITION,DISTANCE_DELETE_CONDITION,NO_SUBSOUND_DELETE_CONDITION,DELETE_NOW_CONDITION};
//enum RootSoundFlag  {INVALID_ROOT_FLAG,TRAVELLING_ROOT_FLAG,PLAYING_ROOT_FLAG,STOPPING_ROOT_FLAG};
enum SonicBoomType  {BULLET_BOOM,ARTILLERY_BOOM,S_PLANE_BOOM,B_PLANE_BOOM};

class SoundInstance{

	int					channel;
	SoundType			sound_type;
	int					timeToDelete;
	SoundEffects*		effect;

	FMOD::Sound*		fmod_sound;
	Ogre::DataStreamPtr strPtr;

	Ogre::String		fileName;
	Ogre::String		resourceGroupName;

	//methods------------------------

	public:

	void				initNull();
					
	void				destroyFMODSound();
	void				destroyEffects();
	void				destroyStreampointer();

	SoundInstance();
	SoundInstance(Ogre::String name,Ogre::String resGroupName,SoundType type); 
	~SoundInstance();

	//channelMethods


	void		setChannel(int channel);
	int			getChannel();

	SoundType	getSoundType();
	void		setSoundType(SoundType type);

	bool		isLooped();
	bool		isRoom();
	bool		isScreen();

	void		updateTimer(unsigned long millis);
	void		create(float distance_to_player = 0);
	void		play();
	void		stop();
	void		stop(unsigned long millis);
	bool		isReadyToPlay();
	bool		isReadyToDelete();
	
	void		setEffect(SoundEffects* effect);
	SoundEffects* getEffect();

	void		setFMODSound(FMOD::Sound* sound);
	FMOD::Sound* getFMODSound();

	void		setStreamPointer(Ogre::DataStreamPtr ptr);
	Ogre::DataStreamPtr getStreamPointer();

	void		setResGroupNName(Ogre::String name,Ogre::String resGroupName);
	Ogre::String getName();
	Ogre::String getResGroupName();
	Ogre::Archive* getFullPath();

};


class ScreenSound : public SoundInstance{

public:

	ScreenSound();
	~ScreenSound();

};

class RootSoundNode;

class SoundNode : public SoundInstance{

	Ogre::SceneNode*	node;

	RootSoundNode*		parent;
	
	void initNullNodes();
	void initNode(Ogre::Vector3 position);
	void destroyNode();

public:

	SoundNode();
	SoundNode(Ogre::String name,Ogre::String resGroupName,bool looped,RootSoundNode* parent,Ogre::Vector3 position = Ogre::Vector3(0,0,0));
	~SoundNode();

	void				setSceneNode(Ogre::SceneNode* node);
	Ogre::SceneNode*	getSceneNode();
	Ogre::Vector3		getPosition();

	RootSoundNode*		getParent();
	void				setParent(RootSoundNode* node);

};

class OgreApplication;

typedef std::vector<SoundNode*> SoundNodeVector;

class RootSoundNode {

	
	RootSoundDeleteCondition	deleteCondition;
	SoundNodeVector*			subSoundVector;
	bool						static_sound;

	Ogre::SceneNode*			main_node;
	Ogre::Vector3				previousPosition;
	Ogre::Vector3				realPlayPosition;
	Ogre::Vector3				velVector;

	SoundEffects*				effects;
	bool						isSuperS;
	SonicBoomType				ss_type;
	float						distance_player;
	
	bool						player_ss_muted;

	//methods

	void initNull();

	void initializeNode(Ogre::Vector3 position,Ogre::SceneNode* attached);
	void initializeVector();
	
	void destroyNode();
	void destroyVector();
	void destroySoundEffects();

	
	void stopAllSounds(unsigned long millis);

	//supersonic methods

	

	bool calculateSuperSonic(Ogre::Vector3 playerpos);
	

	public: 

	RootSoundNode();
	RootSoundNode(RootSoundDeleteCondition state,Ogre::Vector3 position,Ogre::SceneNode* attached = NULL,SoundEffects* effect = NULL);
	~RootSoundNode();

	
	//get/sets

	float getDistance();
	void  setDistance(float dist);

	Ogre::Vector3 getRealPlayPos();

	void setMainNode(Ogre::SceneNode* node);
	Ogre::SceneNode* getMainNode();
	
	Ogre::Vector3 getVelocityVector();
	
	Ogre::Vector3 calculateRealPlayPos(float distance_to_player,Ogre::Vector3 velVector);
	Ogre::Vector3 calculateVelVector(unsigned long millis);

	SoundEffects* getEffect();

	bool isStatic();

	//update methods

	void deleteManual();
	bool isReadyToDelete(float distance_to_player);

	void add(SoundNode* node);
	void remove(SoundNode* node);

	bool isSuperSonic();
	
	void calcPlayerSSMuted(Ogre::Plane player_plane,Ogre::Vector3 velocity);
	bool isPlayerSSMuted();
	void resetPlayerSSMute();

	void updateTimesAndVelocitys(Ogre::Vector3 player_pos,float distance_to_player,unsigned long millis);

};


